package main

import (
	"proxy"
	"proxy/meta"
	"proxy/backend"
	"sync"
	"time"
)

type BackendHandler struct {
	state     *ProxyState
	mu        sync.Mutex
}

func NewBackendHandler(state *ProxyState) *BackendHandler {
	return &BackendHandler{
		state: state,
	}
}

func (h *BackendHandler) OnConnNew(msg *backend.Message) (int, error) {
	backendId := msg.BackendId
	url := msg.Url
	if backendId > 0 {
		log.Infof("backend conn %d re-connect", backendId)
		backend := h.state.meta.ReNewBackend(backendId, url)
		backend.SetConnected(true)
		if backend == nil {
			log.Warningf("backend conn %d re-connect failed", backendId)
			return -1, proxy.ErrNotAvail
		} else {
			log.Infof("backend conn %d re-connect success", backend.Id)
			return backend.Id, nil
		}
	} else {
		log.Infof("backend conn %d first connect", backendId)
	}

	backend, err := h.state.meta.NewBackend(url)

	if err != nil {
		log.Warningf("backend conn %d, register error: '%s'", backendId, err)
		return -1, err
	}

	backend.SetConnected(true)

	log.Infof("backend conn %d register success", backend.Id)
	return backend.Id, nil
}

func (h *BackendHandler) OnConnClose(id int) {
	log.Warningf("backend %d conn closed", id)

	backend := h.state.meta.GetBackend(id)

	if backend == nil {
		return
	}

	// 不要在断开的backend上创建Rtc
	backend.SetConnected(false)
}

// todo： 把now一路传下去
func (h *BackendHandler) OnKeepAlive(backendId int, msg *backend.Message) {
	now := time.Now()

	backend := h.state.meta.GetBackend(backendId)
	if backend == nil {
		log.Warningf("keepalive: backend '%d' not exists", backendId)
		return
	}

	// 即使KeepAlive为空，也要刷新backend的超时
	backend.KeepAliveRtcList([]int{})

	backendRtcIdList := make(map[int][]int, 0)

	for _, conf := range msg.ConfList {

		h.state.meta.KeepAliveConf(now, conf.Id, conf.Kind, conf.RtcList)

		for _, rtcId := range conf.RtcList {
			id, err := meta.ParseRtcId(rtcId)
			if err != nil {
				log.Warningf("keepalive: could not parse rtc id '%s'", rtcId)
				continue
			}
			if rtcIdList, ok := backendRtcIdList[id.BackendId]; ok {
				backendRtcIdList[id.BackendId] = append(rtcIdList, id.RtcId)
			} else {
				backendRtcIdList[id.BackendId] = make([]int, 1)
				backendRtcIdList[id.BackendId][0] = id.RtcId
			}
		}
	}

	for backendId, rtcIdList := range backendRtcIdList {
		backend := h.state.meta.GetBackend(backendId)
		if backend == nil {
			log.Warningf("keepalive: could not find backend '%d', skipped", backendId)
			continue
		}
		backend.KeepAliveRtcList(rtcIdList)
	}
}

// XSwitch会先发送RtcDestroy，再发送Terminate的响应，
// 即使这时删除了Rtc也没问题，不影响向API调用者转发Terminate响应
func (h *BackendHandler) OnRtcDestroy(msg *backend.Message) {
	id, err := meta.ParseRtcId(msg.RtcId)
	if err != nil {
		log.Warningf("OnRtcDestroy: could not parse rtc id '%s'", msg.RtcId)
		return
	}

	log.Infof("OnRtcDestroy: backend %d rtc %d destroyed", id.BackendId, id.RtcId)

	backend := h.state.meta.GetBackend(id.BackendId)

	if backend == nil {
		log.Warningf("OnRtcDestroy: backend %d not in meta database", id.BackendId)
		return
	}

	backend.DelRtc(id.RtcId)

	log.Infof("OnRtcDestroy: deleted rtc '%s' from backend %d", msg.RtcId, id.BackendId)

	conf := h.state.meta.GetConf(msg.ConfId)

	if conf == nil {
		log.Warningf("OnRtcDestroy: conf '%s' not found", msg.ConfId)
		return
	}

	empty := conf.DelRtc(id)

	log.Infof("OnRtcDestroy: deleted rtc '%s' from conf '%s', %d rtc remains", msg.RtcId, msg.ConfId, conf.CountRtc())

	if empty {

		h.state.meta.DelConf(msg.ConfId)

		log.Infof("OnRtcDestroy: deleted conf '%s'", msg.ConfId)
	}
}
